

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/fs.h>

#define DEVNAME "cmdline"

// saved_command_line is not applied from mod
#define TEST_CMDLINE  "BOOT_IMAGE=/vmlinuz-4.4.0-146-lowlatency root=/dev/mapper/iori--vg-root\
 brand=abc model=clink manufacture=rock device=hello product=pad lat=123.456 lng=32.3434 \
"

#define LOGI(fmt, args...) \
	pr_info(DEVNAME "[%04d][@%s]" fmt, __LINE__, __func__, ##args)

#define LOGE(fmt, args...) \
	pr_err(DEVNAME "[%04d][@%s]" fmt, __LINE__, __func__, ##args)


#define BOARD_ITEM_SIZE 32
struct s_board_info{
    char brand[BOARD_ITEM_SIZE];
    char model[BOARD_ITEM_SIZE];
    char manufacture[BOARD_ITEM_SIZE];
    char device[BOARD_ITEM_SIZE];
    char product[BOARD_ITEM_SIZE];
    char lat[BOARD_ITEM_SIZE];   // latitude
    char lng[BOARD_ITEM_SIZE];    // longitude
};


struct pair {
	char key[BOARD_ITEM_SIZE];
	char val[BOARD_ITEM_SIZE];
}bd_info[] = {
	{.key="brand"},
	{.key="model"},
	{.key="manufacture"},
	{.key="device"},
	{.key="product"},
	{.key="lat"},
	{.key="lng"},
};


// return 0 on success -1 fail
static int  parse_key(const char *key, char *val)
{
	char buf[BOARD_ITEM_SIZE];
	char *ps, *pe;
	int n;
	if(key==NULL || key[0]==0){
		return -1;
	}
	n = snprintf(buf, BOARD_ITEM_SIZE, "%s=", key);
#ifdef TEST_CMDLINE
	ps = strstr(TEST_CMDLINE, buf);
#else
	ps = strstr(saved_command_line, buf);
#endif

	if(ps){
		pe = strstr(ps, " ");
		if(pe){
			strncpy(val, ps+n, pe - ps - n);
			return 0;
		}
	}
	return -1;
}

static void parse_board_info(struct s_board_info *bd)
{
	int i;
	memset(bd,0, sizeof(*bd));
	parse_key("brand", bd->brand);
	parse_key("model", bd->model);
	parse_key("manufacture", bd->manufacture);
	parse_key("device", bd->device);
	parse_key("product", bd->product);
	parse_key("lat", bd->lat);
	parse_key("lng", bd->lng);

	for(i=0; i<ARRAY_SIZE(bd_info); i++){
		memset(bd_info[i].val, 0, sizeof(bd_info[i].val));
		if(parse_key(bd_info[i].key, bd_info[i].val) <0){
			LOGE("key %s not found in cmdline", bd_info[i].key);
		}else{
			LOGI("%s=%s", bd_info[i].key, bd_info[i].val);
		}
	}
}


static void test_parse_cmdline(void)
{
	char buff[BOARD_ITEM_SIZE];
	char *cases[] = {"BOOT_IMAGE", "root", "test"};
	int i;
	for(i=0; i<ARRAY_SIZE(cases); i++){
		memset(buff, 0, sizeof(buff));
		if(parse_key(cases[i], buff) < 0){
			LOGE("Key: %s not found", cases[i]);
		}else{
			LOGI("%s=%s", cases[i], buff);
		}	
	}

}

static int __init cmdline_mod_init(void)
{
	struct s_board_info bd;
	LOGI("++");
	test_parse_cmdline();
	parse_board_info(&bd);
	return 0;
}

static void __exit cmdline_mod_exit(void)
{
	LOGI("++");

}


module_init(cmdline_mod_init);
module_exit(cmdline_mod_exit);

MODULE_AUTHOR("tj <tj_wust@163.com>");
MODULE_DESCRIPTION("i2c demo driver");
MODULE_LICENSE("GPL");
